package com.scwatch.core.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.scwatch.common.orm.SearchFilter;
import com.scwatch.core.domain.MemberGroup;
import com.scwatch.core.domain.User;
import com.scwatch.core.domain.UserMemberGroup;
import com.scwatch.core.domain.UserMemberGroup.UserMemberGroupId;
import com.scwatch.core.listener.MemberGroupDeleteListener;
import com.scwatch.core.repository.UserMemberGroupDao;
import com.scwatch.core.service.MemberGroupService;
import com.scwatch.core.service.UserMemberGroupService;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
public class UserMemberGroupServiceImpl implements UserMemberGroupService, MemberGroupDeleteListener {

	private UserMemberGroup findOrCreate(User user, MemberGroup group) {
		UserMemberGroup bean = dao.findOne(new UserMemberGroupId(user.getId(), group.getId()));
		if (bean == null) {
			bean = new UserMemberGroup(user, group);
		}
		return bean;
	}

	@Transactional
	public List<UserMemberGroup> update(User user, Integer[] groupIds, Integer groupId) {
		// 主会员组为null，不更新。
		if (groupId == null) {
			return user.getUserGroups();
		}
		if (groupIds == null) {
			groupIds = new Integer[0];
		} else {
			groupIds = ArrayUtils.removeElement(groupIds, groupId);
		}
		List<UserMemberGroup> userGroups = user.getUserGroups();
		userGroups.clear();
		userGroups.add(findOrCreate(user, groupService.get(groupId)));
		for (Integer id : groupIds) {
			userGroups.add(findOrCreate(user, groupService.get(id)));
		}
		return userGroups;
	}

	@Override
	public Object getUserGroupType(Integer orgId, Integer[] types) {
		Map<String, String[]> params = new HashMap<String, String[]>();
		params.put("EQ_user.org.id",new String[]{String.valueOf(orgId)});
		params.put("IN_group.type",new String[]{String.valueOf(types[0]),String.valueOf(types[1])});
		List<UserMemberGroup> list = dao.findAll(spec(params,orgId,types),new Sort("user.id"));
		List<JSONObject> jsonlist = new ArrayList<>();
		if(list!=null && list.size()>0){
			for (UserMemberGroup user : list){
				JSONObject json = new JSONObject();
				json.put("id",user.getUser().getId());
				json.put("name",user.getUser().getUsername());
				jsonlist.add(json);
			}
		}
		return jsonlist;
	}

    @Override
    public List<UserMemberGroup> findListByParam(Integer orgId, Integer[] types) {
        Map<String, String[]> params = new HashMap<String, String[]>();
        if(orgId!=null){
            params.put("EQ_user.org.id",new String[]{String.valueOf(orgId)});
        }
        params.put("EQ_group.type",new String[]{String.valueOf(types[0])});
        List<UserMemberGroup> list = dao.findAll(spec(params,orgId,types),new Sort("user.id"));
        return list;
    }

    @Override
    public UserMemberGroup findGroupByParam(Integer orgId, String type) {
        Map<String, String[]> params = new HashMap<String, String[]>();
        if(orgId!=null){
            params.put("EQ_user.org.id",new String[]{String.valueOf(orgId)});
        }
        params.put("EQ_group.type",new String[]{type});
        List<UserMemberGroup> list = dao.findAll(spec(params,orgId,null),new Sort("user.id"));
        if(list!=null && list.size()>0){
           return list.get(0);
        }else{
            return null;
        }
    }

    private Specification<UserMemberGroup> spec(
												Map<String, String[]> params,final Integer orgId,final  Integer[] types) {
		Collection<SearchFilter> filters = SearchFilter.parse(params).values();
  		 Specification<UserMemberGroup> sp = SearchFilter.spec(filters, UserMemberGroup.class); //new Specification<UserMemberGroup>() {
		return sp;
	}



	public void preMemberGroupDelete(Integer[] ids) {
		for (Integer id : ids) {
			MemberGroup group = groupService.get(id);
			for (User user : dao.findByUserGroupsGroupId(id)) {
				UserMemberGroup userGroup = new UserMemberGroup(user, group);
				user.getUserGroups().remove(userGroup);
				dao.delete(userGroup);
			}
		}
	}

	private MemberGroupService groupService;

	@Autowired
	public void setMemberGroupService(MemberGroupService groupService) {
		this.groupService = groupService;
	}

	private UserMemberGroupDao dao;

	@Autowired
	public void setDao(UserMemberGroupDao dao) {
		this.dao = dao;
	}
}
